<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 7.3.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/favicon.ico">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon.ico">
  <link rel="mask-icon" href="/favicon.ico" color="#222">

<link rel="stylesheet" href="/css/main.css">

<link rel="stylesheet" href="https://fonts.loli.net/css?family=Lato:300,300italic,400,400italic,700,700italic%7CZCOOL+QingKe+HuangYou:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext">

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha256-DfWjNxDkM94fVBWx1H5BMMp0Zq7luBlV8QRcSES7s+0=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css" integrity="sha256-Vzbj7sDDS/woiFS3uNKo8eIuni59rjyNGtXfstRzStA=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/themes/blue/pace-theme-bounce.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/pace.min.js" integrity="sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0=" crossorigin="anonymous"></script>

<script class="next-config" data-name="main" type="application/json">{"hostname":"www.kaaaaai.cn","root":"/","images":"/images","scheme":"Gemini","darkmode":false,"version":"8.12.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"mac"},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":true,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="规范文档翻译自 raywenderlich.com 的编码规范 目录">
<meta property="og:type" content="article">
<meta property="og:title" content="iOS - Swift 开发规范">
<meta property="og:url" content="https://www.kaaaaai.cn/swift-style-guide.html">
<meta property="og:site_name" content="壹拾肆">
<meta property="og:description" content="规范文档翻译自 raywenderlich.com 的编码规范 目录">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/woailvkai/Kaaaaai.tool.oss/raw/uPic/uPic/9lFrRn-2020%2007%2020.jpg">
<meta property="og:image" content="https://gitee.com/woailvkai/Kaaaaai.tool.oss/raw/uPic/uPic/hxFLPw-2020%2007%2020.jpg">
<meta property="og:image" content="https://gitee.com/woailvkai/Kaaaaai.tool.oss/raw/uPic/uPic/zlcCZh-2020%2007%2020.jpg">
<meta property="article:published_time" content="2019-01-16T12:24:52.000Z">
<meta property="article:modified_time" content="2022-04-26T03:02:44.841Z">
<meta property="article:author" content="Kaaaaai">
<meta property="article:tag" content="EXP">
<meta property="article:tag" content="Swift">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/woailvkai/Kaaaaai.tool.oss/raw/uPic/uPic/9lFrRn-2020%2007%2020.jpg">


<link rel="canonical" href="https://www.kaaaaai.cn/swift-style-guide.html">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://www.kaaaaai.cn/swift-style-guide.html","path":"/swift-style-guide.html","title":"iOS - Swift 开发规范"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>iOS - Swift 开发规范 | 壹拾肆</title>
  
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-102185873-1"></script>
  <script class="next-config" data-name="google_analytics" type="application/json">{"tracking_id":"UA-102185873-1","only_pageview":false}</script>
  <script src="/js/third-party/analytics/google-analytics.js"></script>

  <script src="/js/third-party/analytics/baidu-analytics.js"></script>
  <script async src="https://hm.baidu.com/hm.js?9578d14210d67becef48447e4f6b3f20"></script>



<link rel="dns-prefetch" href="https://waline-server-kaaaaai.vercel.app"> <script type="text/javascript" src="/js/link-highlight.js"></script>

  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
<link rel="alternate" href="/atom.xml" title="壹拾肆" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">壹拾肆</p>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">有些安排是多余的 这片空旷对我有益</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-moments"><a href="/bb/" rel="section"><i class="fa fa-coffee fa-fw"></i>碎片</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%9B%AE%E5%BD%95"><span class="nav-number">1.</span> <span class="nav-text">目录</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%AD%A3%E7%A1%AE%E6%80%A7"><span class="nav-number">2.</span> <span class="nav-text">正确性</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%91%BD%E5%90%8D"><span class="nav-number">3.</span> <span class="nav-text">命名</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%96%87%E7%AB%A0"><span class="nav-number">3.1.</span> <span class="nav-text">文章</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E5%89%8D%E7%BC%80"><span class="nav-number">3.2.</span> <span class="nav-text">类前缀</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%A3%E7%90%86"><span class="nav-number">3.3.</span> <span class="nav-text">代理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E4%B8%8A%E4%B8%8B%E6%96%87%E6%8E%A8%E6%96%AD%E7%9A%84%E7%B1%BB%E5%9E%8B"><span class="nav-number">3.4.</span> <span class="nav-text">使用上下文推断的类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%80%E8%88%AC%E7%9A%84"><span class="nav-number">3.5.</span> <span class="nav-text">一般的</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%AD%E8%A8%80"><span class="nav-number">3.6.</span> <span class="nav-text">语言</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BB%A3%E7%A0%81%E7%BB%84%E7%BB%87"><span class="nav-number">4.</span> <span class="nav-text">代码组织</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8D%8F%E8%AE%AE%E9%81%B5%E5%BE%AA"><span class="nav-number">4.1.</span> <span class="nav-text">协议遵循</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%97%A0%E7%94%A8%E4%BB%A3%E7%A0%81"><span class="nav-number">4.2.</span> <span class="nav-text">无用代码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9C%80%E5%B0%8F%E5%BC%95%E7%94%A8"><span class="nav-number">4.3.</span> <span class="nav-text">最小引用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%A9%BA%E6%A0%BC"><span class="nav-number">5.</span> <span class="nav-text">空格</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B3%A8%E9%87%8A"><span class="nav-number">6.</span> <span class="nav-text">注释</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B1%BB%E5%92%8C%E7%BB%93%E6%9E%84%E4%BD%93"><span class="nav-number">7.</span> <span class="nav-text">类和结构体</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%93%AA%E4%B8%AA%EF%BC%9F"><span class="nav-number">7.1.</span> <span class="nav-text">使用哪个？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%9A%E4%B9%89%E7%9A%84%E4%B8%BE%E4%BE%8B"><span class="nav-number">7.2.</span> <span class="nav-text">定义的举例</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Self-%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">7.3.</span> <span class="nav-text">Self 的使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7"><span class="nav-number">7.4.</span> <span class="nav-text">计算属性</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Final"><span class="nav-number">7.5.</span> <span class="nav-text">Final</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E5%A3%B0%E6%98%8E"><span class="nav-number">8.</span> <span class="nav-text">函数声明</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E4%BD%BF%E7%94%A8"><span class="nav-number">9.</span> <span class="nav-text">函数使用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%97%AD%E5%8C%85%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="nav-number">10.</span> <span class="nav-text">闭包表达式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B1%BB%E5%9E%8B"><span class="nav-number">11.</span> <span class="nav-text">类型</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E9%87%8F"><span class="nav-number">11.1.</span> <span class="nav-text">常量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95%E5%92%8C%E5%8F%AF%E5%8F%98%E7%B1%BB%E5%9E%8B%E5%B1%9E%E6%80%A7"><span class="nav-number">11.2.</span> <span class="nav-text">静态方法和可变类型属性</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%AF%E9%80%89%E7%B1%BB%E5%9E%8B"><span class="nav-number">11.3.</span> <span class="nav-text">可选类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BB%B6%E8%BF%9F%E5%88%9D%E5%A7%8B%E5%8C%96"><span class="nav-number">11.4.</span> <span class="nav-text">延迟初始化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E5%9E%8B%E6%8E%A8%E6%96%AD"><span class="nav-number">11.5.</span> <span class="nav-text">类型推断</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%A9%BA%E6%95%B0%E7%BB%84%E5%92%8C%E7%A9%BA%E5%AD%97%E5%85%B8%E7%9A%84%E7%B1%BB%E5%9E%8B%E6%B3%A8%E9%87%8A"><span class="nav-number">11.5.1.</span> <span class="nav-text">空数组和空字典的类型注释</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%AD%E6%B3%95%E7%B3%96"><span class="nav-number">11.6.</span> <span class="nav-text">语法糖</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0-vs-%E6%96%B9%E6%B3%95"><span class="nav-number">12.</span> <span class="nav-text">函数 vs 方法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86"><span class="nav-number">13.</span> <span class="nav-text">内存管理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BB%B6%E9%95%BF%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">13.1.</span> <span class="nav-text">延长对象的生命周期</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6"><span class="nav-number">14.</span> <span class="nav-text">访问控制</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8E%A7%E5%88%B6%E6%B5%81"><span class="nav-number">15.</span> <span class="nav-text">控制流</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%BB%84%E9%87%91%E8%B7%AF%E5%BE%84"><span class="nav-number">16.</span> <span class="nav-text">黄金路径</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A4%B1%E8%B4%A5%E9%98%B2%E6%8A%A4"><span class="nav-number">16.1.</span> <span class="nav-text">失败防护</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%86%E5%8F%B7"><span class="nav-number">17.</span> <span class="nav-text">分号</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8B%AC%E5%8F%B7"><span class="nav-number">18.</span> <span class="nav-text">括号</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%8D%E6%8E%A8%E8%8D%90%EF%BC%9A"><span class="nav-number">19.</span> <span class="nav-text">不推荐：</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E7%BB%87%E5%92%8C%E5%8C%85-ID"><span class="nav-number">20.</span> <span class="nav-text">组织和包 ID</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE"><span class="nav-number">21.</span> <span class="nav-text">参考文献</span></a></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Kaaaaai"
      src="https://s2.loli.net/2022/03/29/GSJKrCRi4owa9hq.png">
  <p class="site-author-name" itemprop="name">Kaaaaai</p>
  <div class="site-description" itemprop="description">🐨🐨</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">100</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">66</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="sidebar-button site-overview-item animated">
    <button><i class="fa fa-comment"></i>
      Chat
    </button>
  </div>
  <div class="links-of-author site-overview-item animated">
      <span class="links-of-author-item">
        <a href="https://github.com/Kaaaaai" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;Kaaaaai" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/users/8342030/kaaaaai" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;users&#x2F;8342030&#x2F;kaaaaai" rel="noopener" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://www.instagram.com/edisonlllllk" title="Instagram → https:&#x2F;&#x2F;www.instagram.com&#x2F;edisonlllllk" rel="noopener" target="_blank"><i class="fab fa-instagram fa-fw"></i>Instagram</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:root@kaaaaai.cn" title="E-Mail → mailto:root@kaaaaai.cn" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



        </div>
      </div>

      
    <!-- 网易云歌曲 -->
    <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="//music.163.com/outchain/player?type=2&id=421203025&auto=1&height=66"></iframe>
        <div class="back-to-top animated" role="button" aria-label="返回顶部">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://www.kaaaaai.cn/swift-style-guide.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="https://s2.loli.net/2022/03/29/GSJKrCRi4owa9hq.png">
      <meta itemprop="name" content="Kaaaaai">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="壹拾肆">
      <meta itemprop="description" content="🐨🐨">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="iOS - Swift 开发规范 | 壹拾肆">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          iOS - Swift 开发规范
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2019-01-16 20:24:52" itemprop="dateCreated datePublished" datetime="2019-01-16T20:24:52+08:00">2019-01-16</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E7%AC%94%E8%AE%B0/" itemprop="url" rel="index"><span itemprop="name">笔记</span></a>
        </span>
    </span>

  
    <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv">
      <span class="post-meta-item-icon">
        <i class="far fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span id="busuanzi_value_page_pv"></span>
    </span>
  
  <span class="post-meta-item">
    
    <span class="post-meta-item-icon">
      <i class="far fa-comment"></i>
    </span>
    <span class="post-meta-item-text">Waline：</span>
  
    <a title="waline" href="/swift-style-guide.html#waline" itemprop="discussionUrl">
      <span class="post-comments-count waline-comment-count" data-path="/swift-style-guide.html" itemprop="commentCount"></span>
    </a>
  </span>
  
  
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>14k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>13 分钟</span>
    </span>
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <p><em><strong>规范文档翻译自 <a target="_blank" rel="noopener" href="https://github.com/raywenderlich/swift-style-guide">raywenderlich.com 的编码规范</a></strong></em></p>
<h2 id="目录"><a href="#目录" class="headerlink" title="目录"></a>目录</h2><ul>
<li><a href="#correctness">正确性</a></li>
<li><a href="#naming">命名</a></li>
<li><a href="#prose">文章</a></li>
<li><a href="#class_prefixes">类前缀</a></li>
<li><a href="#delegates">代理</a></li>
<li><a href="#use_type_inferred_context">使用上下文推断的类型</a></li>
<li><a href="#generics">一般的</a></li>
<li><a href="#langage">语言</a></li>
<li><a href="#code_organization">代码组织</a></li>
<li><a href="#protocol_conformance">协议遵循</a> </li>
<li><a href="#unused_code">无用代码</a></li>
<li><a href="#minimal_imports">最小引用</a></li>
<li><a href="#spacing">空格</a></li>
<li><a href="#comments">注释</a></li>
<li><a href="#classes_and_structures">类和结构体</a></li>
<li><a href="#use_of_self">Self 的用法</a></li>
<li><a href="#computed_properties">计算属性</a></li>
<li><a href="#final">Final</a></li>
<li><a href="#function_declarations">函数声明</a></li>
<li><a href="#function_calls">函数调用</a></li>
<li><a href="#closure_expressions">闭包表达式</a></li>
<li><a href="#types">类型</a></li>
<li><a href="#constants">常量</a></li>
<li><a href="#static_methods_and_variable_type_properties">静态方法和可变类型属性</a></li>
<li><a href="#optionals">可选类型</a></li>
<li><a href="#lazy_initialization">延迟初始化</a></li>
<li><a href="#type_inference">类型推断</a></li>
<li><a href="#syntactic_sugar">语法糖</a></li>
<li><a href="#functions_vs_methods">函数 vs 方法</a></li>
<li><a href="#memory_management">内存管理</a></li>
<li><a href="#extending_lifetime">延长对象的生命周期</a></li>
<li><a href="#access_control">访问控制</a></li>
<li><a href="#control_flow">控制流</a></li>
<li><a href="#golden_path">黄金路径</a></li>
<li><a href="#failing_guards">失败防护</a></li>
<li><a href="#semicolons">分号</a></li>
<li><a href="#parentheses">括号</a></li>
<li><a href="#organization_and_bundle_indentifier">组织和包 ID</a></li>
<li><a href="#references">参考文献</a></li>
</ul>
<p><b id="correctness"></b></p>
<h2 id="正确性"><a href="#正确性" class="headerlink" title="正确性"></a>正确性</h2><p>努力让你的代码在没有警告的情况下编译。 这条规则决定了许多风格决策，比如使用 #selector 类型而不是字符串字面量。(更多请阅读 <a target="_blank" rel="noopener" href="https://link.jianshu.com/?t=https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md">Swift 3 为什么推荐使用 #selector</a>)。 </p>
<p><b id="naming"></b></p>
<h2 id="命名"><a href="#命名" class="headerlink" title="命名"></a>命名</h2><p>描述性和一致性的命名让软件更易于阅读和理解。使用 <a target="_blank" rel="noopener" href="https://swift.org/documentation/api-design-guidelines/">API 设计规范</a> 中描述的 Swift 命名规范。 一些关键点包括如下：</p>
<ul>
<li>尽量让调用的地方更加简明</li>
<li>简明性优先而不是简洁性</li>
<li>使用驼峰命名法（而不是蛇形命名法）</li>
<li>针对类型（和协议）使用首字母大写，其它都是首字母小写</li>
<li>包含所有需要的单词，同时省略不必要的单词</li>
<li>基于角色的命名，而不是类型</li>
<li>有时候要针对弱引用类型信息进行补充</li>
<li>尽量保持流畅的用法</li>
<li>工厂方法以 make 开头</li>
<li>命名方法的副作用</li>
<li>不可变版本的动词方法要遵循后接 -ed, -ing 的规则</li>
<li>可变版本的名词方法要遵循 formX 的规则</li>
<li>布尔类型应该像断言一样读取</li>
<li>描述 <em>这是什么</em> 的协议应该读作名词</li>
<li>描述 <em>一种能力</em> 的协议应该以 -able 或者 -ible 结尾</li>
<li>使用不会让专家惊讶或让初学者迷惑的术语</li>
<li>通常要避免缩写</li>
<li>使用名称的先例</li>
<li>首选方法和属性而不是自由函数</li>
<li>统一向上或向下包装首字母缩略词和首字母</li>
<li>为相同含义的方法提供相同的基本名称</li>
<li>避免返回类型的重载</li>
<li>选择用于文档的好的参数名</li>
<li>为闭包和元组参数设置标签</li>
<li>利用默认参数的优势</li>
</ul>
<p><b id="prose"></b></p>
<h3 id="文章"><a href="#文章" class="headerlink" title="文章"></a>文章</h3><p>在文章中引用方法时，含义明确是至关重要的。尽可能用最简单的形式引用方法。</p>
<ol>
<li>写一个不带参数的方法。 举例： 下一步，你需要调用方法 <code>addTarget</code>。</li>
<li>写一个带参数标签的方法。 举例： 下一步，你需要调用方法 <code>addTarget(_:action:)</code>。</li>
<li>写一个带参数标签和类型的完整方法。 举例： 下一步, 你需要调用方法 <code>addTarget(_: Any?, action: Selector?)</code>。</li>
</ol>
<p>用上面的例子使用 <code>UIGestureRecognizer</code>, 1 是明确的，也是首选的。</p>
<p>专家提示： 你可以用 Xcode 的跳转栏来查看带有参数标签的方法。<br><img data-src="/images/loading-style-3.gif" data-original="https://gitee.com/woailvkai/Kaaaaai.tool.oss/raw/uPic/uPic/9lFrRn-2020%2007%2020.jpg" alt="9lFrRn-20200720"></p>
<p><b id="class_prefixes"></b></p>
<h3 id="类前缀"><a href="#类前缀" class="headerlink" title="类前缀"></a>类前缀</h3><p>Swift 的类自动被包含在模块分配的命名空间中。不应该再添加类似于 RW 的类前缀。如果不同模块的两个命名冲突，可以在类名前添加模块名来消除歧义。无论如何，仅在少数可能引起混淆的情况下指明模块名。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> SomeModule</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> myClass <span class="operator">=</span> <span class="type">MyModule</span>.<span class="type">UsefulClass</span>()</span><br></pre></td></tr></table></figure>

<p><b id="delegates"></b></p>
<h3 id="代理"><a href="#代理" class="headerlink" title="代理"></a>代理</h3><p>当创建自定义代理方法的时候，未命名的第一个参数应该是代理源。 （ UIKit 包含很多这样的例子。）</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">func</span> <span class="title function_">namePickerView</span>(<span class="keyword">_</span> <span class="params">namePickerView</span>: <span class="type">NamePickerView</span>, <span class="params">didSelectName</span> <span class="params">name</span>: <span class="type">String</span>)</span><br><span class="line"><span class="keyword">func</span> <span class="title function_">namePickerViewShouldReload</span>(<span class="keyword">_</span> <span class="params">namePickerView</span>: <span class="type">NamePickerView</span>) -&gt; <span class="type">Bool</span></span><br></pre></td></tr></table></figure>

<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">func</span> <span class="title function_">didSelectName</span>(<span class="params">namePicker</span>: <span class="type">NamePickerViewController</span>, <span class="params">name</span>: <span class="type">String</span>)</span><br><span class="line"><span class="keyword">func</span> <span class="title function_">namePickerShouldReload</span>() -&gt; <span class="type">Bool</span></span><br></pre></td></tr></table></figure>

<p><b id="use_type_inferred_context"></b></p>
<h3 id="使用上下文推断的类型"><a href="#使用上下文推断的类型" class="headerlink" title="使用上下文推断的类型"></a>使用上下文推断的类型</h3><p>使用上下文推断编译器书写更短更明确的代码。（你也可以阅读 类型推断。)</p>
<p>推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> selector <span class="operator">=</span> <span class="keyword">#selector</span>(viewDidLoad)</span><br><span class="line">view.backgroundColor <span class="operator">=</span> .red</span><br><span class="line"><span class="keyword">let</span> toView <span class="operator">=</span> context.view(forKey: .to)</span><br><span class="line"><span class="keyword">let</span> view <span class="operator">=</span> <span class="type">UIView</span>(frame: .zero)</span><br></pre></td></tr></table></figure>

<p>不推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> selector <span class="operator">=</span> <span class="keyword">#selector</span>(<span class="type">ViewController</span>.viewDidLoad)</span><br><span class="line">view.backgroundColor <span class="operator">=</span> <span class="type">UIColor</span>.red</span><br><span class="line"><span class="keyword">let</span> toView <span class="operator">=</span> context.view(forKey: <span class="type">UITransitionContextViewKey</span>.to)</span><br><span class="line"><span class="keyword">let</span> view <span class="operator">=</span> <span class="type">UIView</span>(frame: <span class="type">CGRect</span>.zero)</span><br></pre></td></tr></table></figure>

<p><b id="generics"></b></p>
<h3 id="一般的"><a href="#一般的" class="headerlink" title="一般的"></a>一般的</h3><p>一般的类型参数应该是描述性的、大写驼峰法命名。当类名没有富有含义的关系或角色时，使用传统的单个大写字母来命名，例如 <code>T</code> 、 <code>U</code> 或 <code>V</code>。</p>
<p>推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">Stack</span>&lt;<span class="type">Element</span>&gt; &#123; <span class="operator">...</span> &#125;</span><br><span class="line"><span class="keyword">func</span> <span class="title function_">write</span>&lt;<span class="type">Target</span>: <span class="type">OutputStream</span>&gt;(<span class="params">to</span> <span class="params">target</span>: <span class="keyword">inout</span> <span class="type">Target</span>)</span><br><span class="line"><span class="keyword">func</span> <span class="title function_">swap</span>&lt;<span class="type">T</span>&gt;(<span class="keyword">_</span> <span class="params">a</span>: <span class="keyword">inout</span> <span class="type">T</span>, <span class="keyword">_</span> <span class="params">b</span>: <span class="keyword">inout</span> <span class="type">T</span>)</span><br></pre></td></tr></table></figure>

<p>不推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">Stack</span>&lt;<span class="type">T</span>&gt; &#123; <span class="operator">...</span> &#125;</span><br><span class="line"><span class="keyword">func</span> <span class="title function_">write</span>&lt;target: <span class="type">OutputStream</span>&gt;(<span class="params">to</span> <span class="params">target</span>: <span class="keyword">inout</span> target)</span><br><span class="line"><span class="keyword">func</span> <span class="title function_">swap</span>&lt;<span class="type">Thing</span>&gt;(<span class="keyword">_</span> <span class="params">a</span>: <span class="keyword">inout</span> <span class="type">Thing</span>, <span class="keyword">_</span> <span class="params">b</span>: <span class="keyword">inout</span> <span class="type">Thing</span>)</span><br></pre></td></tr></table></figure>

<p><b id="langage"></b></p>
<h3 id="语言"><a href="#语言" class="headerlink" title="语言"></a>语言</h3><p>使用美式英语拼写来匹配 Apple 的 API。</p>
<p>推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> color <span class="operator">=</span> <span class="string">&quot;red&quot;</span></span><br></pre></td></tr></table></figure>

<p>不推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colour <span class="operator">=</span> <span class="string">&quot;red&quot;</span></span><br></pre></td></tr></table></figure>

<p><b id="code_organization"></b></p>
<h2 id="代码组织"><a href="#代码组织" class="headerlink" title="代码组织"></a>代码组织</h2><p>用扩展将代码组织为功能逻辑块。每个扩展都应该添加 &#x2F;&#x2F; MARK: - 注释，以保证代码的结构清晰。</p>
<p><b id="protocol_conformance"></b></p>
<h3 id="协议遵循"><a href="#协议遵循" class="headerlink" title="协议遵循"></a>协议遵循</h3><p>推荐为协议方法加一个单独的扩展，尤其是为一个模型加入协议遵循的时候。这可以让有关联的协议方法被分组在一起，也可以简化用类关联方法向这个类添加协议的指令。</p>
<p>推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyViewController</span>: <span class="title class_ inherited__">UIViewController</span> &#123;</span><br><span class="line">  <span class="comment">// 类填充在这</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// MARK: - UITableViewDataSource</span></span><br><span class="line"><span class="keyword">extension</span> <span class="title class_">MyViewController</span>: <span class="title class_ inherited__">UITableViewDataSource</span> &#123;</span><br><span class="line">  <span class="comment">// table view 的数据源方法</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// MARK: - UIScrollViewDelegate</span></span><br><span class="line"><span class="keyword">extension</span> <span class="title class_">MyViewController</span>: <span class="title class_ inherited__">UIScrollViewDelegate</span> &#123;</span><br><span class="line">  <span class="comment">// scroll view 的代理方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>不推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyViewController</span>: <span class="title class_ inherited__">UIViewController</span>, <span class="title class_ inherited__">UITableViewDataSource</span>, <span class="title class_ inherited__">UIScrollViewDelegate</span> &#123;</span><br><span class="line">  <span class="comment">// 所有方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>因为编译器不允许在派生类中重新声明协议遵循，所以并不总是需要复制基类的扩展组。如果派生类是一个终端类，并且只有少数方法会被覆盖，那么这个原则尤为正确。应由作者自行决定何时保留扩展组- 。</p>
<p>对于 UIKit 中的视图控制器，可考虑将生命周期、自定义存取器和 IBAction 分组在单独的类扩展中。</p>
<p><b id="unused_code"></b></p>
<h3 id="无用代码"><a href="#无用代码" class="headerlink" title="无用代码"></a>无用代码</h3><p>无用代码（僵尸代码），包括 Xcode 模板代码和占位注释，应该被移除掉。教程或书籍中教用户使用的注释代码除外。</p>
<p>仅实现简单调用父类，但与教程无直接关联的方法应该被移除。这里包括任何为空的或无用的 UIApplicationDelegate 方法。</p>
<p>推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">override</span> <span class="keyword">func</span> <span class="title function_">tableView</span>(<span class="keyword">_</span> <span class="params">tableView</span>: <span class="type">UITableView</span>, <span class="params">numberOfRowsInSection</span> <span class="params">section</span>: <span class="type">Int</span>) -&gt; <span class="type">Int</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="type">Database</span>.contacts.count</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>不推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">override</span> <span class="keyword">func</span> <span class="title function_">didReceiveMemoryWarning</span>() &#123;</span><br><span class="line">  <span class="keyword">super</span>.didReceiveMemoryWarning()</span><br><span class="line">  <span class="comment">// 任何可以重建资源的处理。</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">override</span> <span class="keyword">func</span> <span class="title function_">numberOfSections</span>(<span class="params">in</span> <span class="params">tableView</span>: <span class="type">UITableView</span>) -&gt; <span class="type">Int</span> &#123;</span><br><span class="line">  <span class="comment">// #warning 未完成的实现，返回节数。</span></span><br><span class="line">  <span class="keyword">return</span> <span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">override</span> <span class="keyword">func</span> <span class="title function_">tableView</span>(<span class="keyword">_</span> <span class="params">tableView</span>: <span class="type">UITableView</span>, <span class="params">numberOfRowsInSection</span> <span class="params">section</span>: <span class="type">Int</span>) -&gt; <span class="type">Int</span> &#123;</span><br><span class="line">  <span class="comment">// #warning 未完成的实现，返回行数。</span></span><br><span class="line">  <span class="keyword">return</span> <span class="type">Database</span>.contacts.count</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="minimal_imports"></b></p>
<h3 id="最小引用"><a href="#最小引用" class="headerlink" title="最小引用"></a>最小引用</h3><p>引用最小化。举个例子，引用 <code>Foundation</code> 就足够的情况下不要再引用 <code>UIKit</code> 。</p>
<p><b id="spacing"></b></p>
<h2 id="空格"><a href="#空格" class="headerlink" title="空格"></a>空格</h2><ul>
<li><p>用两个字符缩进比用制表符缩进更节省空间，同时能防止换行。务必在 Xcode 和项目中设置这个偏好，如下所示：<br><img data-src="/images/loading-style-3.gif" data-original="https://gitee.com/woailvkai/Kaaaaai.tool.oss/raw/uPic/uPic/hxFLPw-2020%2007%2020.jpg" alt="hxFLPw-20200720"></p>
</li>
<li><p>方法大括号和其他大括号（ <code>if</code> &#x2F; <code>else</code> &#x2F; <code>switch</code> &#x2F; <code>while</code> 等）总是在和语句相同的行写左括号，而在新行写右括号。</p>
</li>
<li><p>提示：你可以通过选中一些代码（或按 ⌘A 选中全部）然后按 Control-I （或在目录中选择编辑器 -&gt; 结构 -&gt; 重新缩进）的方式来重新缩进代码。一些 Xcode 模板代码会使用 4 个空格的制表符硬编码，这就是一个修正它的好方法。<br>推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> user.isHappy &#123;</span><br><span class="line"><span class="comment">// 做一件事</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line"><span class="comment">// 做另一件事</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<p>不推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> user.isHappy</span><br><span class="line">&#123;</span><br><span class="line">  <span class="comment">// 做一件事</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="comment">// 做另一件事</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>方法之间应该只有一个空行，这样有助于视觉清晰和组织。方法中的空白应该按功能分隔代码，但在一个方法中有很多段意味着你应该将它们封装进不同的方法。</li>
<li>冒号总是在左边没有空格而右边有空格。比较特殊的是三元运算符 <code>? :</code>、空字典 <code>[:]</code> 和带有未命名参数 <code>(_:)</code> 的 <code>#selector</code> 语法 .<br>推荐：<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">TestDatabase</span>: <span class="title class_ inherited__">Database</span> &#123;</span><br><span class="line">  <span class="keyword">var</span> data: [<span class="type">String</span>: <span class="type">CGFloat</span>] <span class="operator">=</span> [<span class="string">&quot;A&quot;</span>: <span class="number">1.2</span>, <span class="string">&quot;B&quot;</span>: <span class="number">3.2</span>]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<p>不推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">TestDatabase</span> : <span class="title class_ inherited__">Database</span> &#123;</span><br><span class="line">  <span class="keyword">var</span> data :[<span class="type">String</span>:<span class="type">CGFloat</span>] <span class="operator">=</span> [<span class="string">&quot;A&quot;</span> : <span class="number">1.2</span>, <span class="string">&quot;B&quot;</span>:<span class="number">3.2</span>]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>长行应该在 70 个字符左右被换行（这里并非硬性限制，可自行调整）。<br>避免在行结尾的地方附上空白。<br>在每个文件的结尾处增加一个单独的换行符。</p>
<p><b id="comments"></b></p>
<h2 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h2><p>需要的时候，用注释来解释一个特定的代码片段 <strong>为什么</strong> 做某件事。注释应保持要么是最新的，要么就被删除。</p>
<p>为了避免块注释和代码内联，代码应该尽可能自文档化。 例外：这不含那些注释被用于生成文档的情况 。</p>
<p><b id="classes_and_structures"></b></p>
<h2 id="类和结构体"><a href="#类和结构体" class="headerlink" title="类和结构体"></a>类和结构体</h2><h3 id="使用哪个？"><a href="#使用哪个？" class="headerlink" title="使用哪个？"></a>使用哪个？</h3><p>请记住，结构体有 <a target="_blank" rel="noopener" href="https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_144">值语义</a>。对没有标识的事物应用结构体。一个包含 [a, b, c] 的数组和另一个包含 [a, b, c] 的数组是完全一样的。他们是可以完全互换的。使用第一个数组还是第二个数组都无所谓，因为他们代表着完全相同的事物。这就是为什么数组是结构体。</p>
<p>类有 <a target="_blank" rel="noopener" href="https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_145">引用语义</a>。对有标识或有具体生命周期的事物应用类。你需要将人建模为一个类，因为不同两个人对象是两个不同的事物。只是因为两个人拥有相同的名字和生日不意味着他们是同一个人。但是人的生日应该是一个结构体，因为 1950 年 3 月 3 日和任何其它的 1950 年 3 月 3 日日期对象是相同的。日期本身没有标识。</p>
<p>有时，事物应该是结构体但需要遵循 <code>AnyObject</code>，或在历史上已经被建模为类 （<code>NSDate</code> 、 <code>NSSet</code>）。尽可能尝试遵循这些原则。</p>
<h3 id="定义的举例"><a href="#定义的举例" class="headerlink" title="定义的举例"></a>定义的举例</h3><p>这是一个风格良好的类定义例子：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Circle</span>: <span class="title class_ inherited__">Shape</span> &#123;</span><br><span class="line">  <span class="keyword">var</span> x: <span class="type">Int</span>, y: <span class="type">Int</span></span><br><span class="line">  <span class="keyword">var</span> radius: <span class="type">Double</span></span><br><span class="line">  <span class="keyword">var</span> diameter: <span class="type">Double</span> &#123;</span><br><span class="line">    <span class="keyword">get</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> radius <span class="operator">*</span> <span class="number">2</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">set</span> &#123;</span><br><span class="line">      radius <span class="operator">=</span> newValue <span class="operator">/</span> <span class="number">2</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">init</span>(<span class="params">x</span>: <span class="type">Int</span>, <span class="params">y</span>: <span class="type">Int</span>, <span class="params">radius</span>: <span class="type">Double</span>) &#123;</span><br><span class="line">    <span class="keyword">self</span>.x <span class="operator">=</span> x</span><br><span class="line">    <span class="keyword">self</span>.y <span class="operator">=</span> y</span><br><span class="line">    <span class="keyword">self</span>.radius <span class="operator">=</span> radius</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">convenience</span> <span class="keyword">init</span>(<span class="params">x</span>: <span class="type">Int</span>, <span class="params">y</span>: <span class="type">Int</span>, <span class="params">diameter</span>: <span class="type">Double</span>) &#123;</span><br><span class="line">    <span class="keyword">self</span>.<span class="keyword">init</span>(x: x, y: y, radius: diameter <span class="operator">/</span> <span class="number">2</span>)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">override</span> <span class="keyword">func</span> <span class="title function_">area</span>() -&gt; <span class="type">Double</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="type">Double</span>.pi <span class="operator">*</span> radius <span class="operator">*</span> radius</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">extension</span> <span class="title class_">Circle</span>: <span class="title class_ inherited__">CustomStringConvertible</span> &#123;</span><br><span class="line">  <span class="keyword">var</span> description: <span class="type">String</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;center = <span class="subst">\(centerString)</span> area = <span class="subst">\(area())</span>&quot;</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">private</span> <span class="keyword">var</span> centerString: <span class="type">String</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;(<span class="subst">\(x)</span>,<span class="subst">\(y)</span>)&quot;</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上面的例子遵循了以下风格规范：</p>
<ul>
<li>用后面有空格而前面没有空格的冒号，为属性、变量、常量、参数声明和其它语句指定类型，例如：x: Int 和 Circle: Shape。</li>
<li>如果多个变量和结构体共享一个共同的目的 &#x2F; 上下文，则可以在同一行中定义。</li>
<li>缩进 getter、setter 的定义和属性观察器。</li>
<li>不要再添加如 internal 的默认修饰符。类似的，当重写一个方法时，不要再重复添加访问修饰符。</li>
<li>在扩展中组织额外功能（例如打印）。</li>
<li>隐藏非共享的实现细节，例如 centerString 在扩展中使用 private 访问控制。</li>
</ul>
<p><b id="use_of_self"></b></p>
<h3 id="Self-的使用"><a href="#Self-的使用" class="headerlink" title="Self 的使用"></a>Self 的使用</h3><p>为了简洁，请避免使用 self 关键词，Swift 不需要用它来访问一个对象属性或调用它的方法。</p>
<p>仅在编译器需要时（在 @escaping 闭包或初始化函数中，消除参数与属性的歧义）才使用 self。换句话说，如果不需要 self 就能编译通过，则可以忽略它。</p>
<p><b id="computed_properties"></b></p>
<h3 id="计算属性"><a href="#计算属性" class="headerlink" title="计算属性"></a>计算属性</h3><p>为了简洁，如果一个计算属性是只读的，则可以忽略 get 子句。仅在提供了 set 子句的情况下才需要 get 子句。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> diameter: <span class="type">Double</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> radius <span class="operator">*</span> <span class="number">2</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> diameter: <span class="type">Double</span> &#123;</span><br><span class="line">  <span class="keyword">get</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> radius <span class="operator">*</span> <span class="number">2</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="final"></b></p>
<h3 id="Final"><a href="#Final" class="headerlink" title="Final"></a>Final</h3><p>在教程中将类或成员标记为 <code>final</code> 会从主题分散注意力，而且也没必要。 尽管如此，<code>final</code> 的使用有时可以表明你的意图，且值得你这样做。在下面的例子中，<code>Box</code> 有特定的目的，且并不打算在派生类中自定义它。标记为 <code>final</code> 可以使它更清晰。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 用这个 Box 类将任何一般类型转换为引用类型。</span></span><br><span class="line"><span class="keyword">final</span> <span class="keyword">class</span> <span class="title class_">Box</span>&lt;<span class="type">T</span>&gt; &#123;</span><br><span class="line">  <span class="keyword">let</span> value: <span class="type">T</span></span><br><span class="line">  <span class="keyword">init</span>(<span class="keyword">_</span> <span class="params">value</span>: <span class="type">T</span>) &#123;</span><br><span class="line">    <span class="keyword">self</span>.value <span class="operator">=</span> value</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="function_declarations"></b></p>
<h2 id="函数声明"><a href="#函数声明" class="headerlink" title="函数声明"></a>函数声明</h2><p>在一行中保持较短的方法声明，包括左括号：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">func</span> <span class="title function_">reticulateSplines</span>(<span class="params">spline</span>: [<span class="type">Double</span>]) -&gt; <span class="type">Bool</span> &#123;</span><br><span class="line">  <span class="comment">// 在这里写网格代码</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>对于签名较长的函数，则需在合适的位置换行，然后在后续的行中加一个额外的换行：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">func</span> <span class="title function_">reticulateSplines</span>(<span class="params">spline</span>: [<span class="type">Double</span>], <span class="params">adjustmentFactor</span>: <span class="type">Double</span>,</span><br><span class="line">    <span class="params">translateConstant</span>: <span class="type">Int</span>, <span class="params">comment</span>: <span class="type">String</span>) -&gt; <span class="type">Bool</span> &#123;</span><br><span class="line">  <span class="comment">// 在这里写网络代码</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="function_calls"></b></p>
<h2 id="函数使用"><a href="#函数使用" class="headerlink" title="函数使用"></a>函数使用</h2><p>在一行中保持较短的函数使用，像这样：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> success <span class="operator">=</span> reticulateSplines(splines)</span><br></pre></td></tr></table></figure>

<p>如果是包装调用，则需在合适的位置换行，然后在后续的行中加一个额外的换行：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> success <span class="operator">=</span> reticulateSplines(</span><br><span class="line">  spline: splines,</span><br><span class="line">  adjustmentFactor: <span class="number">1.3</span>,</span><br><span class="line">  translateConstant: <span class="number">2</span>,</span><br><span class="line">  comment: <span class="string">&quot;normalize the display&quot;</span>)</span><br></pre></td></tr></table></figure>

<p><b id="closure_expressions"></b></p>
<h2 id="闭包表达式"><a href="#闭包表达式" class="headerlink" title="闭包表达式"></a>闭包表达式</h2><p>仅在参数列表最后有个单独的闭包表达式参数时，使用尾随闭包语法。给闭包参数定义一个描述性的命名。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">UIView</span>.animate(withDuration: <span class="number">1.0</span>) &#123;</span><br><span class="line">  <span class="keyword">self</span>.myView.alpha <span class="operator">=</span> <span class="number">0</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">UIView</span>.animate(withDuration: <span class="number">1.0</span>, animations: &#123;</span><br><span class="line">  <span class="keyword">self</span>.myView.alpha <span class="operator">=</span> <span class="number">0</span></span><br><span class="line">&#125;, completion: &#123; finished <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">self</span>.myView.removeFromSuperview()</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">UIView</span>.animate(withDuration: <span class="number">1.0</span>, animations: &#123;</span><br><span class="line">  <span class="keyword">self</span>.myView.alpha <span class="operator">=</span> <span class="number">0</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="type">UIView</span>.animate(withDuration: <span class="number">1.0</span>, animations: &#123;</span><br><span class="line">  <span class="keyword">self</span>.myView.alpha <span class="operator">=</span> <span class="number">0</span></span><br><span class="line">&#125;) &#123; f <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">self</span>.myView.removeFromSuperview()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>对于上下文清晰的单独表达式闭包，使用隐式返回：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">attendeeList.sort &#123; a, b <span class="keyword">in</span></span><br><span class="line">  a <span class="operator">&gt;</span> b</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>使用尾随闭包的链式方法应该清晰且在上下文中易读。作者将自行抉择空格、换行、命名与匿名参数的使用。举例：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> value <span class="operator">=</span> numbers.map &#123; <span class="variable">$0</span> <span class="operator">*</span> <span class="number">2</span> &#125;.filter &#123; <span class="variable">$0</span> <span class="operator">%</span> <span class="number">3</span> <span class="operator">==</span> <span class="number">0</span> &#125;.index(of: <span class="number">90</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> value <span class="operator">=</span> numbers</span><br><span class="line">  .map &#123;<span class="variable">$0</span> <span class="operator">*</span> <span class="number">2</span>&#125;</span><br><span class="line">  .filter &#123;<span class="variable">$0</span> <span class="operator">&gt;</span> <span class="number">50</span>&#125;</span><br><span class="line">  .map &#123;<span class="variable">$0</span> <span class="operator">+</span> <span class="number">10</span>&#125;</span><br></pre></td></tr></table></figure>

<p><b id="types"></b></p>
<h2 id="类型"><a href="#类型" class="headerlink" title="类型"></a>类型</h2><p>请尽可能多的使用 Swift 原生类型。 Swift 提供了 Objective-C 桥接，所以当你需要的时候你仍然可以使用全套方法。</p>
<p><strong>推荐:</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> width <span class="operator">=</span> <span class="number">120.0</span>                                    <span class="comment">// Double</span></span><br><span class="line"><span class="keyword">let</span> widthString <span class="operator">=</span> (width <span class="keyword">as</span> <span class="type">NSNumber</span>).stringValue    <span class="comment">// String</span></span><br></pre></td></tr></table></figure>

<p><strong>不推荐:</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> width: <span class="type">NSNumber</span> <span class="operator">=</span> <span class="number">120.0</span>                          <span class="comment">// NSNumber</span></span><br><span class="line"><span class="keyword">let</span> widthString: <span class="type">NSString</span> <span class="operator">=</span> width.stringValue        <span class="comment">// NSString</span></span><br></pre></td></tr></table></figure>
<p>在 Sprite Kit 代码中，使用 <code>CGFloat</code> 可以让你的代码避免太多转换，从而让你的代码更加简洁。</p>
<p><b id="constants"></b></p>
<h3 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h3><p>使用 <code>let</code> 关键字来定义常量，使用 <code>var</code> 关键字来定义变量。如果变量的值不会改变，则要使用 <code>let</code> 来代替 <code>var</code> 。</p>
<p><strong>提示:</strong> 一个比较好的技巧就是定义所有的东西都使用 <code>let</code> , 当编译器警告的时候再改为 <code>var</code> 。</p>
<p>你可以在一个类型里面去定义常量而不是在类型的实例变量中去使用类型属性。使用 <code>static let</code> 去声明一个类型属性作为常量。用这种方式声明类型属性比声明全局变量更推荐，因为这种方式更能和实例属性区分开。举例：</p>
<p><strong>推荐:</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">enum</span> <span class="title class_">Math</span> &#123;</span><br><span class="line">  <span class="keyword">static</span> <span class="keyword">let</span> e <span class="operator">=</span> <span class="number">2.718281828459045235360287</span></span><br><span class="line">  <span class="keyword">static</span> <span class="keyword">let</span> root2 <span class="operator">=</span> <span class="number">1.41421356237309504880168872</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> hypotenuse <span class="operator">=</span> side <span class="operator">*</span> <span class="type">Math</span>.root2</span><br></pre></td></tr></table></figure>
<p><strong>注意：</strong> 使用无大小写枚举的优势，就是它不会被意外的实例化，而只是单纯的作为一个命名空间。</p>
<p><strong>不推荐:</strong></p>
<p>let e &#x3D; 2.718281828459045235360287  &#x2F;&#x2F; 污染全局命名空间<br>let root2 &#x3D; 1.41421356237309504880168872</p>
<p>let hypotenuse &#x3D; side * root2 &#x2F;&#x2F; 什么 root2?</p>
<p><b id="static_methods_and_variable_type_properties"></b></p>
<h3 id="静态方法和可变类型属性"><a href="#静态方法和可变类型属性" class="headerlink" title="静态方法和可变类型属性"></a>静态方法和可变类型属性</h3><p>静态方法和类型属性跟全局函数和全局变量的工作原理类似，应当谨慎使用。当功能的作用域是一个特定类型或需要与 Objective-C 交互时，它们非常有用。</p>
<p><b id="optionals"></b></p>
<h3 id="可选类型"><a href="#可选类型" class="headerlink" title="可选类型"></a>可选类型</h3><p>在可接受 nil 值的情况下，使用 <code>?</code> 声明变量和函数返回类型为可选类型。</p>
<p>用 <code>!</code> 声明的隐式解包类型，仅用于稍后在使用前初始化的实例变量，比如将在 <code>viewDidLoad</code> 中创建子视图。</p>
<p>当访问一个可选值时，如果值仅被访问一次或在链中有许多可选项时，使用可选链：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">self</span>.textContainer<span class="operator">?</span>.textLabel<span class="operator">?</span>.setNeedsDisplay()</span><br></pre></td></tr></table></figure>
<p>当一次性解包和执行多个操作更方便时，使用可选绑定：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> <span class="keyword">let</span> textContainer <span class="operator">=</span> <span class="keyword">self</span>.textContainer &#123;</span><br><span class="line">  <span class="comment">// 用 textContainer 做很多事情</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在命名可选变量和属性时，需避免类似 <code>optionalString</code> 或 <code>maybeView</code> 这样的命名，因为他们的可选性已经体现在类型声明中了。</p>
<p>对于可选绑定，适当时使用原始名称，而不是使用像 <code>unwrappedView</code> 或 <code>actualLabel</code> 这样的名称。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> subview: <span class="type">UIView</span>?</span><br><span class="line"><span class="keyword">var</span> volume: <span class="type">Double</span>?</span><br><span class="line"></span><br><span class="line"><span class="comment">// later on...</span></span><br><span class="line"><span class="keyword">if</span> <span class="keyword">let</span> subview <span class="operator">=</span> subview, <span class="keyword">let</span> volume <span class="operator">=</span> volume &#123;</span><br><span class="line">  <span class="comment">// 使用展开的 subview 和 volume 做某件事</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> optionalSubview: <span class="type">UIView</span>?</span><br><span class="line"><span class="keyword">var</span> volume: <span class="type">Double</span>?</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="keyword">let</span> unwrappedSubview <span class="operator">=</span> optionalSubview &#123;</span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">let</span> realVolume <span class="operator">=</span> volume &#123;</span><br><span class="line">    <span class="comment">// 使用 unwrappedSubview 和 volume 做某件事</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="lazy_initialization"></b></p>
<h3 id="延迟初始化"><a href="#延迟初始化" class="headerlink" title="延迟初始化"></a>延迟初始化</h3><p>在更细粒度地控制对象声明周期时考虑使用延迟初始化。 对于 <code>UIViewController</code> ，延迟初始化视图是非常正确的。你也可以直接调用 <code>&#123; &#125;()</code> 的闭包或调用私有工厂方法。例如：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">lazy</span> <span class="keyword">var</span> locationManager: <span class="type">CLLocationManager</span> <span class="operator">=</span> <span class="keyword">self</span>.makeLocationManager()</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">func</span> <span class="title function_">makeLocationManager</span>() -&gt; <span class="type">CLLocationManager</span> &#123;</span><br><span class="line">  <span class="keyword">let</span> manager <span class="operator">=</span> <span class="type">CLLocationManager</span>()</span><br><span class="line">  manager.desiredAccuracy <span class="operator">=</span> kCLLocationAccuracyBest</span><br><span class="line">  manager.delegate <span class="operator">=</span> <span class="keyword">self</span></span><br><span class="line">  manager.requestAlwaysAuthorization()</span><br><span class="line">  <span class="keyword">return</span> manager</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>注意：</strong></p>
<ul>
<li>因为没有发生循环引用，所以这里不需要 <code>[unowned self]</code>。</li>
<li>位置管理器对弹出 UI 向用户申请权限有副作用，所以细颗粒地控制在这里是有意义的。</li>
</ul>
<p><b id="type_inference"></b></p>
<h3 id="类型推断"><a href="#类型推断" class="headerlink" title="类型推断"></a>类型推断</h3><p>优先选择简洁紧凑的代码，让编译器为单个实例的常量或变量推断类型。类型推断也适合于小（非空）的数组和字典。需要时，请指明特定类型，如 <code>CGFloat</code> 或 <code>Int16</code>。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> message <span class="operator">=</span> <span class="string">&quot;Click the button&quot;</span></span><br><span class="line"><span class="keyword">let</span> currentBounds <span class="operator">=</span> computeViewBounds()</span><br><span class="line"><span class="keyword">var</span> names <span class="operator">=</span> [<span class="string">&quot;Mic&quot;</span>, <span class="string">&quot;Sam&quot;</span>, <span class="string">&quot;Christine&quot;</span>]</span><br><span class="line"><span class="keyword">let</span> maximumWidth: <span class="type">CGFloat</span> <span class="operator">=</span> <span class="number">106.5</span></span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> message: <span class="type">String</span> <span class="operator">=</span> <span class="string">&quot;Click the button&quot;</span></span><br><span class="line"><span class="keyword">let</span> currentBounds: <span class="type">CGRect</span> <span class="operator">=</span> computeViewBounds()</span><br><span class="line"><span class="keyword">let</span> names <span class="operator">=</span> [<span class="type">String</span>]()</span><br></pre></td></tr></table></figure>
<h4 id="空数组和空字典的类型注释"><a href="#空数组和空字典的类型注释" class="headerlink" title="空数组和空字典的类型注释"></a>空数组和空字典的类型注释</h4><p>为空数组和空字典使用类型注释。（对于分配给大型、多行文字的数组和字典，使用类型注释。）</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> names: [<span class="type">String</span>] <span class="operator">=</span> []</span><br><span class="line"><span class="keyword">var</span> lookup: [<span class="type">String</span>: <span class="type">Int</span>] <span class="operator">=</span> [:]</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> names <span class="operator">=</span> [<span class="type">String</span>]()</span><br><span class="line"><span class="keyword">var</span> lookup <span class="operator">=</span> [<span class="type">String</span>: <span class="type">Int</span>]()</span><br></pre></td></tr></table></figure>
<p><strong>注意：</strong>遵循此原则意味着选择描述性命名比之前更重要。</p>
<p><b id="syntactic_sugar"></b></p>
<h3 id="语法糖"><a href="#语法糖" class="headerlink" title="语法糖"></a>语法糖</h3><p>推荐使用类型声明简短的版本，而不是完整的泛型语法。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> deviceModels: [<span class="type">String</span>]</span><br><span class="line"><span class="keyword">var</span> employees: [<span class="type">Int</span>: <span class="type">String</span>]</span><br><span class="line"><span class="keyword">var</span> faxNumber: <span class="type">Int</span>?</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> deviceModels: <span class="type">Array</span>&lt;<span class="type">String</span>&gt;</span><br><span class="line"><span class="keyword">var</span> employees: <span class="type">Dictionary</span>&lt;<span class="type">Int</span>, <span class="type">String</span>&gt;</span><br><span class="line"><span class="keyword">var</span> faxNumber: <span class="type">Optional</span>&lt;<span class="type">Int</span>&gt;</span><br></pre></td></tr></table></figure>

<p><b id="functions_vs_methods"></b></p>
<h2 id="函数-vs-方法"><a href="#函数-vs-方法" class="headerlink" title="函数 vs 方法"></a>函数 vs 方法</h2><p>不附属于类或类型的自有函数应该被谨慎使用。可能的话，首选方法而不是自由函数。这有助于可读性和易领悟性。</p>
<p>自由函数最适用于它们与任何特定类或实例无关的情况。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> sorted <span class="operator">=</span> items.mergeSorted()  <span class="comment">// 容易领悟的</span></span><br><span class="line">rocket.launch()  <span class="comment">// 模型的行为</span></span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> sorted <span class="operator">=</span> mergeSort(items)  <span class="comment">// 难以领悟的</span></span><br><span class="line">launch(<span class="operator">&amp;</span>rocket)</span><br><span class="line">自由函数异常</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> tuples <span class="operator">=</span> <span class="built_in">zip</span>(a, b)  <span class="comment">// 作为自由函数感到自然（对称）</span></span><br><span class="line"><span class="keyword">let</span> value <span class="operator">=</span> <span class="built_in">max</span>(x, y, z)  <span class="comment">// 另一个感到自然的自由函数</span></span><br></pre></td></tr></table></figure>

<p><b id="memory_management"></b></p>
<h2 id="内存管理"><a href="#内存管理" class="headerlink" title="内存管理"></a>内存管理</h2><p>代码 （甚至非生产环境、教程演示的代码）都不应该出现循环引用。分析你的对象图并用 <code>weak</code> 和 <code>unowned</code> 来防止强循环引用。或者，使用值类型（ <code>struct</code>、<code>enum</code> ）来彻底防止循环引用。</p>
<p><b id="extending_lifetime"></b></p>
<h3 id="延长对象的生命周期"><a href="#延长对象的生命周期" class="headerlink" title="延长对象的生命周期"></a>延长对象的生命周期</h3><p>使用惯用语法 <code>[weak self]</code> 和 <code>guard let strongSelf = self else &#123; return &#125; </code>来延长对象的生命周期。 在 <code>self</code> 超出闭包生命周期不明显的地方，<code>[weak self]</code> 更优于 <code>[unowned self]</code>。 明确地延长生命周期优于可选解包。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">resource.request().onComplete &#123; [<span class="keyword">weak</span> <span class="keyword">self</span>] response <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">guard</span> <span class="keyword">let</span> strongSelf <span class="operator">=</span> <span class="keyword">self</span> <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">let</span> model <span class="operator">=</span> strongSelf.updateModel(response)</span><br><span class="line">  strongSelf.updateUI(model)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 如果在响应返回前 self 被释放，则可能导致崩溃</span></span><br><span class="line">resource.request().onComplete &#123; [<span class="keyword">unowned</span> <span class="keyword">self</span>] response <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">let</span> model <span class="operator">=</span> <span class="keyword">self</span>.updateModel(response)</span><br><span class="line">  <span class="keyword">self</span>.updateUI(model)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 内存回收可以发生在更新模型和更新 UI 之间</span></span><br><span class="line">resource.request().onComplete &#123; [<span class="keyword">weak</span> <span class="keyword">self</span>] response <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">let</span> model <span class="operator">=</span> <span class="keyword">self</span><span class="operator">?</span>.updateModel(response)</span><br><span class="line">  <span class="keyword">self</span><span class="operator">?</span>.updateUI(model)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="access_control"></b></p>
<h2 id="访问控制"><a href="#访问控制" class="headerlink" title="访问控制"></a>访问控制</h2><p>在教程中，完整的访问控制注释会分散主题且是不必要的。然而，适时地使用 <code>private</code> 和 <code>fileprivate</code> 会使代码更加清晰，也会有助于封装。 在合理情况下，<code>private</code> 要优于 <code>fileprivate</code>。 使用扩展可能会要求你使用 <code>fileprivate</code>。</p>
<p>只有需要完整的访问控制规范时，才显式地使用 <code>open</code> 、 <code>public</code> 和 <code>internal</code>。</p>
<p>将访问控制用作前置属性说明符。仅有 <code>static</code> 说明符或诸如 <code>@IBAction</code> 、 <code>@IBOutlet</code> 和 <code>@discardableResult</code> 的属性应该放在访问控制前面。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">let</span> message <span class="operator">=</span> <span class="string">&quot;Great Scott!&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">TimeMachine</span> &#123;  </span><br><span class="line">  <span class="keyword">fileprivate</span> <span class="keyword">dynamic</span> <span class="keyword">lazy</span> <span class="keyword">var</span> fluxCapacitor <span class="operator">=</span> <span class="type">FluxCapacitor</span>()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fileprivate</span> <span class="keyword">let</span> message <span class="operator">=</span> <span class="string">&quot;Great Scott!&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">TimeMachine</span> &#123;  </span><br><span class="line">  <span class="keyword">lazy</span> <span class="keyword">dynamic</span> <span class="keyword">fileprivate</span> <span class="keyword">var</span> fluxCapacitor <span class="operator">=</span> <span class="type">FluxCapacitor</span>()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="control_flow"></b></p>
<h2 id="控制流"><a href="#控制流" class="headerlink" title="控制流"></a>控制流</h2><p>优先选择 <code>for</code> 循环的 <code>for-in</code> 格式而不是 <code>while-condition-increment</code> 格式。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> <span class="keyword">_</span> <span class="keyword">in</span> <span class="number">0</span><span class="operator">..&lt;</span><span class="number">3</span> &#123;</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;Hello three times&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (index, person) <span class="keyword">in</span> attendeeList.enumerated() &#123;</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;<span class="subst">\(person)</span> is at position #<span class="subst">\(index)</span>&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> index <span class="keyword">in</span> <span class="built_in">stride</span>(from: <span class="number">0</span>, to: items.count, by: <span class="number">2</span>) &#123;</span><br><span class="line">  <span class="built_in">print</span>(index)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> index <span class="keyword">in</span> (<span class="number">0</span><span class="operator">...</span><span class="number">3</span>).reversed() &#123;</span><br><span class="line">  <span class="built_in">print</span>(index)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> i <span class="operator">=</span> <span class="number">0</span></span><br><span class="line"><span class="keyword">while</span> i <span class="operator">&lt;</span> <span class="number">3</span> &#123;</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;Hello three times&quot;</span>)</span><br><span class="line">  i <span class="operator">+=</span> <span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> i <span class="operator">=</span> <span class="number">0</span></span><br><span class="line"><span class="keyword">while</span> i <span class="operator">&lt;</span> attendeeList.count &#123;</span><br><span class="line">  <span class="keyword">let</span> person <span class="operator">=</span> attendeeList[i]</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;<span class="subst">\(person)</span> is at position #<span class="subst">\(i)</span>&quot;</span>)</span><br><span class="line">  i <span class="operator">+=</span> <span class="number">1</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="golden_path"></b></p>
<h2 id="黄金路径"><a href="#黄金路径" class="headerlink" title="黄金路径"></a>黄金路径</h2><p>当使用条件语句编码时，代码的左边距应该是 「黄金」或「快乐」的路径。就是不要嵌套 if 语句。多个返回语句是可以的。<code>guard</code> 语句就是因为这个创建的。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">func</span> <span class="title function_">computeFFT</span>(<span class="params">context</span>: <span class="type">Context</span>?, <span class="params">inputData</span>: <span class="type">InputData</span>?) <span class="keyword">throws</span> -&gt; <span class="type">Frequencies</span> &#123;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">guard</span> <span class="keyword">let</span> context <span class="operator">=</span> context <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="type">FFTError</span>.noContext</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">guard</span> <span class="keyword">let</span> inputData <span class="operator">=</span> inputData <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="type">FFTError</span>.noInputData</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 用上下文和输入计算频率</span></span><br><span class="line">  <span class="keyword">return</span> frequencies</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">func</span> <span class="title function_">computeFFT</span>(<span class="params">context</span>: <span class="type">Context</span>?, <span class="params">inputData</span>: <span class="type">InputData</span>?) <span class="keyword">throws</span> -&gt; <span class="type">Frequencies</span> &#123;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">let</span> context <span class="operator">=</span> context &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">let</span> inputData <span class="operator">=</span> inputData &#123;</span><br><span class="line">      <span class="comment">// 用上下文和输入计算频率</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">return</span> frequencies</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">throw</span> <span class="type">FFTError</span>.noInputData</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="type">FFTError</span>.noContext</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>当用 <code>guard</code> 或 <code>if let</code> 解包多个可选值时，在可能的情况下使用最下化复合版本嵌套。举例：</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">guard</span> <span class="keyword">let</span> number1 <span class="operator">=</span> number1,</span><br><span class="line">      <span class="keyword">let</span> number2 <span class="operator">=</span> number2,</span><br><span class="line">      <span class="keyword">let</span> number3 <span class="operator">=</span> number3 <span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="built_in">fatalError</span>(<span class="string">&quot;impossible&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 用数字做某事</span></span><br></pre></td></tr></table></figure>
<p><strong>不推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> <span class="keyword">let</span> number1 <span class="operator">=</span> number1 &#123;</span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">let</span> number2 <span class="operator">=</span> number2 &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">let</span> number3 <span class="operator">=</span> number3 &#123;</span><br><span class="line">      <span class="comment">// 用数字做某事</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="built_in">fatalError</span>(<span class="string">&quot;impossible&quot;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="built_in">fatalError</span>(<span class="string">&quot;impossible&quot;</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="built_in">fatalError</span>(<span class="string">&quot;impossible&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><b id="failing_guards"></b></p>
<h3 id="失败防护"><a href="#失败防护" class="headerlink" title="失败防护"></a>失败防护</h3><p>对于用某些方法退出，防护语句是必要的。一般地，它应该是一行简洁的语句，比如： <code>return</code> 、 <code>throw</code> 、 <code>break</code> 、 <code>continue</code> 和 <code>fatalError()</code>。应该避免大的代码块。如果清理代码被用在多个退出点，则可以考虑用 <code>defer</code> 块来避免清理代码的重复。</p>
<p><b id="semicolons"></b></p>
<h2 id="分号"><a href="#分号" class="headerlink" title="分号"></a>分号</h2><p>在 <code>Swift</code> 中，每条代码语句后面都不需要加分号。只有在你希望在一行中结合多条语句，才需要加分号。</p>
<p>不要在用分号分隔的单行中写多条语句。</p>
<p>推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> swift <span class="operator">=</span> <span class="string">&quot;not a scripting language&quot;</span></span><br></pre></td></tr></table></figure>
<p>不推荐：</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> swift <span class="operator">=</span> <span class="string">&quot;not a scripting language&quot;</span>;</span><br></pre></td></tr></table></figure>
<p>注：Swift 非常不同于 JavaScript。在 JavaScript 中忽略分号 <a target="_blank" rel="noopener" href="http://stackoverflow.com/questions/444080/do-you-recommend-using-semicolons-after-every-statement-in-javascript">一般被认为不安全</a>。</p>
<p><b id="parentheses"></b></p>
<h2 id="括号"><a href="#括号" class="headerlink" title="括号"></a>括号</h2><p>条件周围的括号是不必要的，应该被忽略。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> name <span class="operator">==</span> <span class="string">&quot;Hello&quot;</span> &#123;</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;World&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="不推荐："><a href="#不推荐：" class="headerlink" title="不推荐："></a>不推荐：</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (name <span class="operator">==</span> <span class="string">&quot;Hello&quot;</span>) &#123;</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;World&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在更大的表达式中，可选括号有时可以让代码读起来更清晰。</p>
<p><strong>推荐：</strong></p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> playerMark <span class="operator">=</span> (player <span class="operator">==</span> current <span class="operator">?</span> <span class="string">&quot;X&quot;</span> : <span class="string">&quot;O&quot;</span>)</span><br></pre></td></tr></table></figure>

<p><b id="organization_and_bundle_indentifier"></b></p>
<h2 id="组织和包-ID"><a href="#组织和包-ID" class="headerlink" title="组织和包 ID"></a>组织和包 ID</h2><p>涉及到 Xcode 项目的地方，组织应该被设置为 <code>Ray Wenderlich</code> 并且包 ID 应该被设置为 <code>com.razeware.TutorialName</code> ，其中 <code>TutorialName</code> 是教程项目的名字。<br><img data-src="/images/loading-style-3.gif" data-original="https://gitee.com/woailvkai/Kaaaaai.tool.oss/raw/uPic/uPic/zlcCZh-2020%2007%2020.jpg" alt="zlcCZh-20200720"></p>
<p><b id="references"></b></p>
<h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ul>
<li><a target="_blank" rel="noopener" href="https://swift.org/documentation/api-design-guidelines/">Swift API 设计规范</a></li>
<li><a target="_blank" rel="noopener" href="https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/index.html">Swift 编程语言</a></li>
<li><a target="_blank" rel="noopener" href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html">Swift 与 Cocoa 和 Objective-C 一起使用</a></li>
<li><a target="_blank" rel="noopener" href="https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/index.html">Swift 标准库参考</a></li>
</ul>
<p>Aufree</p>
<blockquote>
<p>原文地址：<a target="_blank" rel="noopener" href="https://github.com/raywenderlich/swift-style-guide#memory-management">https://github.com/raywenderlich/swift-s...</a></p>
</blockquote>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="reward-container">
  <div></div>
  <button>
    请喝咖啡
  </button>
  <div class="post-reward">
      <div>
        <img src="/images/loading-style-3.gif" data-original="https://s2.loli.net/2022/07/02/Gce8a5QAqrZ3X9R.gif" alt="Kaaaaai 微信">
        <span>微信</span>
      </div>

  </div>
</div>

          

<div class="post-copyright">
<ul>
  <li class="post-copyright-author">
      <strong>本文作者： </strong>Kaaaaai
  </li>
  <li class="post-copyright-link">
      <strong>本文链接：</strong>
      <a href="https://www.kaaaaai.cn/swift-style-guide.html" title="iOS - Swift 开发规范">https://www.kaaaaai.cn/swift-style-guide.html</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>

          <div class="post-tags">
              <a href="/tags/EXP/" rel="tag"><i class="fa fa-tag"></i> EXP</a>
              <a href="/tags/Swift/" rel="tag"><i class="fa fa-tag"></i> Swift</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/happy-new-year-2019.html" rel="prev" title="喘口气上来">
                  <i class="fa fa-chevron-left"></i> 喘口气上来
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/on-the-road.html" rel="next" title="在路上">
                  在路上 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






    <div class="comments" id="waline"></div>
</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Kaaaaai</span>
</div>
<div class="wordcount">
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-line"></i>
    </span>
    <span title="站点总字数">234k</span>
  </span>
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">3:33</span>
  </span>
</div>
<div class="busuanzi-count">
    <span class="post-meta-item" id="busuanzi_container_site_uv">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-item" id="busuanzi_container_site_pv">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>
  <!-- time -->
  <div id="show-time">
    <span id="span_dt_dt"></span>
  </div>
  <script>
      function show_date_time() {
        window.setTimeout("show_date_time()", 1000);
        BirthDay = new Date("6/23/2017 19:37:01");
        today = new Date();
        //总时间
        timeold = (today.getTime() - BirthDay.getTime());
        sectimeold = timeold / 1000
        secondsold = Math.floor(sectimeold);
        msPerDay = 24 * 60 * 60 * 1000
        e_daysold = timeold / msPerDay
        daysold = Math.floor(e_daysold);
        e_hrsold = (e_daysold - daysold) * 24;
        hrsold = Math.floor(e_hrsold);
        e_minsold = (e_hrsold - hrsold) * 60;
        minsold = Math.floor((e_hrsold - hrsold) * 60);
        seconds = Math.floor((e_minsold - minsold) * 60);
        span_dt_dt.innerHTML = "已存活 " + daysold + " 天 " + hrsold + " 小时 " + minsold + " 分 " + seconds + " 秒";
    }
    show_date_time();
  </script>

    </div>
  </footer>

  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.5.0/pjax.min.js" integrity="sha256-3NkoLDrmHLTYj7csHIZSr0MHAFTXth7Ua/DDt4MRUAg=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js" integrity="sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js" integrity="sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  
<script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.0/search.js" integrity="sha256-vXZMYLEqsROAXkEw93GGIvaB2ab+QW6w3+1ahD9nXXA=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>
<script class="next-config" data-name="chatra" type="application/json">{"enable":true,"async":true,"id":"QXLRxXcsfrRJR2KTG"}</script>
<script src="/js/third-party/chat/chatra.js"></script>
<script async src="https://call.chatra.io/chatra.js"></script>



  <script src="/js/third-party/fancybox.js"></script>

  <script src="/js/third-party/pace.js"></script>

  
  <script data-pjax async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>




<script class="next-config" data-name="waline" type="application/json">{"lang":"zh-cn","enable":true,"serverURL":"https://waline-server-kaaaaai.vercel.app","cssUrl":"https://unpkg.com/@waline/client@v2/dist/waline.css","commentCount":true,"pageview":false,"placeholder":"请文明评论呀","avatar":"mm","meta":["nick","mail","link"],"pageSize":10,"visitor":false,"comment_count":true,"requiredFields":[],"libUrl":"//unpkg.com/@waline/client@v2/dist/waline.js","el":"#waline","comment":true,"path":"/swift-style-guide.html"}</script>
<link rel="stylesheet" href="https://unpkg.com/@waline/client@v2/dist/waline.css">
<script>
document.addEventListener('page:loaded', () => {
  NexT.utils.loadComments(CONFIG.waline.el).then(() =>
    NexT.utils.getScript(CONFIG.waline.libUrl, { condition: window.Waline })
  ).then(() => 
    Waline.init(Object.assign({}, CONFIG.waline,{ el: document.querySelector(CONFIG.waline.el) }))
  );
});
</script>


        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: true,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(r){r.imageLazyLoadSetting.processImages=t;var a=r.imageLazyLoadSetting.isSPA,n=r.imageLazyLoadSetting.preloadRatio||1,d=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(t){(a||t)&&(d=o());for(var e,i=0;i<d.length;i++)0<=(e=(e=d[i]).getBoundingClientRect()).bottom&&0<=e.left&&e.top<=(r.innerHeight*n||document.documentElement.clientHeight*n)&&function(){var t,e,a,n,o=d[i];e=function(){d=d.filter(function(t){return o!==t}),r.imageLazyLoadSetting.onImageLoaded&&r.imageLazyLoadSetting.onImageLoaded(o)},(t=o).dataset.loaded||(t.hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(a=new Image,n=t.getAttribute("data-original"),a.onload=function(){t.src=n,t.removeAttribute("data-original"),t.setAttribute("data-loaded",!0),e&&e()},a.onerror=function(){t.removeAttribute("data-original"),t.setAttribute("data-loaded",!1),t.src=n},t.src!==n&&(a.src=n)))}()}function e(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",e),r.addEventListener("resize",e),r.addEventListener("orientationchange",e)}(this);</script></body>
</html>
